Hvorfor producerer visse tilfældige strenge farver, når de indtastes som baggrundsfarver i HTML? For eksempel: test ... producerer et dokument med en rød baggrund på tværs af alle browsere og platforme. Interessant, mens chucknorri også producerer en rød baggrund, producerer chucknorr en gul baggrund. Hvad sker der her?
2020-12-07 21:55:40
Det er en holdover fra Netscape-dagene: Manglende cifre behandles som 0 [...]. Et forkert ciffer fortolkes simpelthen som 0. For eksempel er værdierne # F0F0F0, F0F0F0, F0F0F, #FxFxFx og FxFxFx de samme. Det er fra blogindlægget En smule rant om Microsoft Internet Explorer's farveanalyse, der dækker det i detaljer, inklusive forskellige længder af farveværdier osv. Hvis vi anvender reglerne igen fra blogindlægget, får vi følgende: Erstat alle ikke-gyldige hexadecimale tegn med 0'er: chucknorris bliver c00c0000000 Bliv ud til det næste samlede antal tegn, der kan deles med 3 (11 → 12): c00c 0000 0000 Opdel i tre lige store grupper, hvor hver komponent repræsenterer den tilsvarende farvekomponent i en RGB-farve: RGB (c00c, 0000, 0000) Trunker hvert af argumenterne fra højre ned til to tegn. Som endelig giver følgende resultat: RGB (c0, 00, 00) = # C00000 eller RGB (192, 0, 0) Her er et eksempel, der demonstrerer bgcolor-attributten i aktion for at producere denne "fantastiske" farveprøve:Dette besvarer også den anden del af spørgsmålet: Hvorfor producerer bgcolor = "chucknorr" en gul farve? Nå, hvis vi anvender reglerne, er strengen: c00c00000 => c00 c00 000 => c0 c0 00 [RGB (192, 192, 0)] Hvilket giver en lysegul guldfarve. Da strengen starter med 9 tegn, beholder vi den anden 'C' denne gang, hvorfor den ender i den endelige farveværdi. Jeg stødte oprindeligt på dette, da nogen påpegede, at du kunne gøre color = "crap", og det kommer godt ud brun. | Jeg er ked af at være uenig, men ifølge reglerne for parsing af en ældre farveværdi indsendt af @Yuhong Bao svarer chucknorris IKKE til # CC0000, men snarere til # C00000, en meget ens, men lidt anden nuance af rød. Jeg brugte Firefox ColorZilla-tilføjelsen til at bekræfte dette. Reglerne siger: lav strengen til en længde, der er et multiplum af 3 ved at tilføje 0s: chucknorris0 adskil strengen i 3 lige lange strenge: chuc knor ris0 trunker hver streng til 2 tegn: ch kn ri beholder hex-værdierne, og tilføj 0'er, hvor det er nødvendigt: C0 00 00 Jeg var i stand til at bruge disse regler til korrekt fortolkning af følgende strenge: Lykkeamuletter Held LuckBeALady LuckBeALadyTonight Gangnam Style OPDATERING: De originale svarere, der sagde, at farven var # CC0000, har siden redigeret deres svar for at inkludere korrektionen. | De fleste browsere ignorerer simpelthen NON-hex-værdier i din farvestreng og erstatter nuller med ikke-hexadecimale cifre. ChuCknorris oversættes til c00c0000000. På dette tidspunkt deler browseren strengen i tre lige store sektioner, hvilket indikerer røde, grønne og blå værdier: c00c 0000 0000. Ekstra bits i hvert afsnit ignoreres, hvilket gør det endelige resultat # c00000, som er en rødlig farve. Bemærk, dette gælder ikke for CSS-farveparsing, der følger CSS-standarden. chuck norris Mr T ninjaturtle syg crap græs Rødlig
Samme som ovenfor
Sort
| Årsagen er, at browseren ikke kan forstå det og prøve på en eller anden måde at oversætte det til, hvad det kan forstå, og i dette tilfælde til en hexadecimal værdi! ... chucknorris starter med c, som er genkendt tegn i hexadecimal, og det konverterer også alle ukendte tegn til 0! Så chucknorris i hexadecimal format bliver: c00c00000000, alle andre tegn bliver 0 og c forbliver hvor de er ... Nu bliver de divideret med 3 for RGB (rød, grøn, blå) ... R: c00c, G: 0000, B: 0000 ... Men vi ved, at gyldig hexadecimal for RGB kun er 2 tegn, betyder R: c0, G: 00, B: 00 Så det virkelige resultat er: bgcolor = "# c00000"; Jeg tilføjede også trinene i billedet som en hurtig reference til dig: | Browseren forsøger at konvertere chucknorris til hex-farvekode, fordi det ikke er en gyldig værdi. I chucknorris er alt undtagen c ikke en gyldig hex-værdi. Så det bliver konverteret til c00c00000000. Hvilket bliver til # c00000, en skygge af rødt. Dette ser ud til at være et problem primært med Internet Explorer og Opera (12), da både Chrome (31) og Firefox (26) bare ignorerer dette. P.S. Tallene i parentes er de browserversioner, jeg testede på. På en lettere tone Chuck Norris overholder ikke webstandarder. Webstandarder er i overensstemmelse til ham. # BADA55 | WHATWG HTML-specifikationen har den nøjagtige algoritme til parsing af en ældre farveværdi: https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-a-legacy-colour-value. Koden Netscape Classic, der bruges til at analysere farvestrenge, er open source: https://dxr.mozilla.org/classic/source/lib/layout/layimage.c#155. Bemærk f.eks., At hvert tegn er parset som et hexadecimalt tal og derefter flyttes til et 32-bit heltal uden at kontrollere for overløb. Kun otte hexadecimale cifre passer ind i et 32-bit heltal, hvorfor kun de sidste 8 tegn tages i betragtning. Efter parsing af hex-cifrene i 32-bit heltal trunkeres de derefter i 8-bit heltal ved at dividere dem med 16, indtil de passer ind i 8-bit, hvilket er grunden til, at førende nuller ignoreres. Opdatering: Denne kode matcher ikke nøjagtigt, hvad der er defineret i specifikationen, men den eneste forskel, der er et par linjer med kode. Jeg tror, det er disse linjer, der blev tilføjet (i Netscape 4): hvis (bytes_per_val> 4) { bytes_per_val = 4; } | Svar: Browseren vil forsøge at konvertere chucknorris til en hexadecimal værdi. Da c er det eneste gyldige hex-tegn i chucknorris, bliver værdien til: c00c00000000 (0 for alle ugyldige værdier). Browseren deler derefter resultatet i 3 grupperinger: Rød = c00c, Grøn = 0000, Blå = 0000. Da gyldige hex-værdier for html-baggrunde kun indeholder 2 cifre for hver farvetype (r, g, b), afkortes de sidste 2 cifre fra hver gruppe, hvilket efterlader en rgb-værdi på c00000, som er en mursten-rødlig tonet farve. | chucknorris starter med c, og browseren læser det ind i en hexadecimal værdi. Fordi A, B, C, D, E og F er tegn i hexadecimal. Browseren konverterer chucknorris til en hexadecimal værdi, C00C00000000. Derefter konverteres C00C00000000 hexadecimal værdi til RGB-format (divideret med 3): C00C00000000 ⇒ R: C00C, G: 0000, B: 0000 Browseren har kun brug for to cifre for at angive farven: R: C00C, G: 0000, B: 0000 ⇒ R: C0, G: 00, B: 00 ⇒ C00000 Vis endelig bgcolor = C00000 i webbrowseren. Her er et eksempel, der demonstrerer det:| Reglerne for at analysere farver på ældre attributter involverer yderligere trin end dem, der er nævnt i eksisterende svar. Den afkortede komponent til 2 cifre del er beskrevet som: Kassér alle tegn undtagen de sidste 8 Kassér forreste nuller en efter en, så længe alle komponenter har et førende nul Kassér alle tegn undtagen de første 2 Nogle eksempler: oooFoooFoooF 000F 000F 000F <- udskift, pude og klump 0F 0F 0F <- ledende nuller afkortet 0F 0F 0F <- afkortet til 2 tegn fra højre oooFooFFoFFF 000F 00FF 0FFF <- udskift, pude og klump 00F 0FF FFF <- ledende nuller afkortet 00 0F FF <- afkortet til 2 tegn fra højre ABCooooooABCooooooABCoooooo ABC000000 ABC000000 ABC000000 <- udskift, pad og klump BC000000 BC000000 BC000000 <- afkortet til 8 tegn fra venstre BC BC BC <- afkortet til 2 tegn fra højre AoCooooooAoCooooooAoCoooooo A0C000000 A0C000000 A0C000000 <- udskift, pude og klump 0C000000 0C000000 0C000000 <- afkortet til 8 tegn fra venstre C000000 C000000 C000000 <- ledende nuller afkortet C0 C0 C0 <- afkortet til 2 tegn fra højre Nedenfor er en delvis implementering af algoritmen. Det håndterer ikke fejl eller tilfælde, hvor brugeren indtaster en gyldig farve. funktion parseColor (input) { // todo: return error hvis input er "" input = input.trim (); // todo: return error hvis input er "transparent" // todo: returner tilsvarende #rrggbb, hvis input er en navngivet farve // todo: return #rrggbb hvis input matcher #rgb // todo: udskift unicode-kodepunkter, der er større end U + FFFF med 00 hvis (input.length> 128) { input = input.slice (0, 128); } hvis (input.charAt (0) === "#") { input = input.skive (1); } input = input.replace (/ [^ 0-9A-Fa-f] / g, "0"); mens (input.length === 0 || input.length% 3> 0) { input + = "0"; } var r = input.slice (0, input.length / 3); var g = input.skive (input.længde / 3, input.længde * 2/3); var b = input.slice (input.længde * 2/3); hvis (r. længde> 8) { r = r. skive (-8); g = g.skive (-8); b = b.skive (-8); } mens (r.length> 2 && r.charAt (0) === "0" && g.charAt (0) === "0" && b.charAt (0) === "0") { r = r. skive (1); g = g. skive (1); b = b. skive (1); } hvis (r. længde> 2) { r = r. skive (0, 2); g = g. skive (0, 2); b = b.skive (0, 2); } returner "#" + r.padStart (2, "0") + g.padStart (2, "0") + b.padStart (2, "0"); } $ (funktion () { $ ("# input"). on ("ændre", funktion () { var input = $ (dette) .val (); var color = parseColor (input); var $ celler = $ ("# resultat tbody td"); $ celler.eq (0) .attr ("bgcolor", input); $ celler.eq (1) .attr ("bgfarve", farve); varværdi: https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-a-legacy-colour-value. Koden Netscape Classic, der bruges til at analysere farvestrenge, er open source: https://dxr.mozilla.org/classic/source/lib/layout/layimage.c#155. Bemærk f.eks., At hvert tegn er parset som et hexadecimalt tal og derefter flyttes til et 32-bit heltal uden at kontrollere for overløb. Kun otte hexadecimale cifre passer ind i et 32-bit heltal, hvorfor kun de sidste 8 tegn tages i betragtning. Efter parsing af hex-cifrene i 32-bit heltal trunkeres de derefter i 8-bit heltal ved at dividere dem med 16, indtil de passer ind i 8-bit, hvilket er grunden til, at førende nuller ignoreres. Opdatering: Denne kode matcher ikke nøjagtigt, hvad der er defineret i specifikationen, men den eneste forskel, der er et par linjer med kode. Jeg tror, det er disse linjer, der blev tilføjet (i Netscape 4): hvis (bytes_per_val> 4) { bytes_per_val = 4; } | Svar: Browseren vil forsøge at konvertere chucknorris til en hexadecimal værdi. Da c er det eneste gyldige hex-tegn i chucknorris, bliver værdien til: c00c00000000 (0 for alle ugyldige værdier). Browseren deler derefter resultatet i 3 grupperinger: Rød = c00c, Grøn = 0000, Blå = 0000. Da gyldige hex-værdier for html-baggrunde kun indeholder 2 cifre for hver farvetype (r, g, b), afkortes de sidste 2 cifre fra hver gruppe, hvilket efterlader en rgb-værdi på c00000, som er en mursten-rødlig tonet farve. | chucknorris starter med c, og browseren læser det ind i en hexadecimal værdi. Fordi A, B, C, D, E og F er tegn i hexadecimal. Browseren konverterer chucknorris til en hexadecimal værdi, C00C00000000. Derefter konverteres C00C00000000 hexadecimal værdi til RGB-format (divideret med 3): C00C00000000 ⇒ R: C00C, G: 0000, B: 0000 Browseren har kun brug for to cifre for at angive farven: R: C00C, G: 0000, B: 0000 ⇒ R: C0, G: 00, B: 00 ⇒ C00000 Vis endelig bgcolor = C00000 i webbrowseren. Her er et eksempel, der demonstrerer det: chucknorris c00c00000000 c00000 | Reglerne for at analysere farver på ældre attributter involverer yderligere trin end dem, der er nævnt i eksisterende svar. Den afkortede komponent til 2 cifre del er beskrevet som: Kassér alle tegn undtagen de sidste 8 Kassér forreste nuller en efter en, så længe alle komponenter har et førende nul Kassér alle tegn undtagen de første 2 Nogle eksempler: oooFoooFoooF 000F 000F 000F <- udskift, pude og klump 0F 0F 0F <- ledende nuller afkortet 0F 0F 0F <- afkortet til 2 tegn fra højre oooFooFFoFFF 000F 00FF 0FFF <- udskift, pude og klump 00F 0FF FFF <- ledende nuller afkortet 00 0F FF <- afkortet til 2 tegn fra højre ABCooooooABCooooooABCoooooo ABC000000 ABC000000 ABC000000 <- udskift, pad og klump BC000000 BC000000 BC000000 <- afkortet til 8 tegn fra venstre BC BC BC <- afkortet til 2 tegn fra højre AoCooooooAoCooooooAoCoooooo A0C000000 A0C000000 A0C000000 <- udskift, pude og klump 0C000000 0C000000 0C000000 <- afkortet til 8 tegn fra venstre C000000 C000000 C000000 <- ledende nuller afkortet C0 C0 C0 <- afkortet til 2 tegn fra højre Nedenfor er en delvis implementering af algoritmen. Det håndterer ikke fejl eller tilfælde, hvor brugeren indtaster en gyldig farve. funktion parseColor (input) { // todo: return error hvis input er "" input = input.trim (); // todo: return error hvis input er "transparent" // todo: returner tilsvarende #rrggbb, hvis input er en navngivet farve // todo: return #rrggbb hvis input matcher #rgb // todo: udskift unicode-kodepunkter, der er større end U + FFFF med 00 hvis (input.length> 128) { input = input.slice (0, 128); } hvis (input.charAt (0) === "#") { input = input.skive (1); } input = input.replace (/ [^ 0-9A-Fa-f] / g, "0"); mens (input.length === 0 || input.length% 3> 0) { input + = "0"; } var r = input.slice (0, input.length / 3); var g = input.skive (input.længde / 3, input.længde * 2/3); var b = input.slice (input.længde * 2/3); hvis (r. længde> 8) { r = r. skive (-8); g = g.skive (-8); b = b.skive (-8); } mens (r.length> 2 && r.charAt (0) === "0" && g.charAt (0) === "0" && b.charAt (0) === "0") { r = r. skive (1); g = g. skive (1); b = b. skive (1); } hvis (r. længde> 2) { r = r. skive (0, 2); g = g. skive (0, 2); b = b.skive (0, 2); } returner "#" + r.padStart (2, "0") + g.padStart (2, "0") + b.padStart (2, "0"); } $ (funktion () { $ ("# input"). on ("ændre", funktion () { var input = $ (dette) .val (); var color = parseColor (input); var $ celler = $ ("# resultat tbody td"); $ celler.eq (0) .attr ("bgcolor", input); $ celler.eq (1) .attr ("bgfarve", farve); var chucknorris c00c00000000 c00000